package com.sky.chapter3.executor;

import lombok.SneakyThrows;

import java.time.LocalTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.*;

/**
 * @author : wushikai
 * <p>
 * date : 2022-04-09
 */
public class ExecutorDemo {

    private static ExecutorService executorService;

    private static Set<Callable<String>> callableHashSet;        //使用一个 容器来 存放 线程 ;


    static {


        executorService = Executors.newFixedThreadPool(3);

        callableHashSet = new HashSet<>();
        callableHashSet.add(() -> "Task c");
        callableHashSet.add(() -> "Task b");
        callableHashSet.add(() -> "Task a");


    }

    /**
     *
     */
    private static void testExecute() {

        executorService.execute(new Runnable() { //什么都不返回
            @Override
            public void run() {
                System.out.println("Runnable1   test Executor.execute() ");
            }
        });


        executorService.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println("Runnable2  test Executor.execute() ");
                } catch (InterruptedException e) {
                    System.out.println("ERROR  " + e.getMessage() + "  " + e.getClass().getCanonicalName());
                }

            }
        });

        executorService.execute(new Runnable() {

            @Override
            public void run() {
                System.out.println("Runnable3  test Executor.execute() ");
                while (true){

                    if (LocalTime.now().isAfter(LocalTime.of(10, 26, 22))){
                        break;
                    }
                }

            }
        });



        /*
        * 1、跟 shutdown() 一样，先停止接收新submit的任务；
        2、忽略队列里等待的任务；
        3、尝试将正在执行的任务interrupt中断；
        4、返回未执行的任务列表；
        * */
        List<Runnable> runnables = executorService.shutdownNow();

        System.out.println("executorService.shutdownNow().size() ==>  " + runnables.size());
        for (Runnable runnable : runnables) {
            System.out.println(new Thread(runnable).getName());
        }

    }


    public static void testRunCall() {

        try {


            Future runnableFuture = executorService.submit(() -> System.out.println("Asynchronous task"));


            //如果任务结束执行则返回 null
            System.out.println("runnableFuture.get()=" + runnableFuture.get());


            Future<String> callableFuture = executorService.submit(() -> {
                Thread.sleep(1000);
                Thread.currentThread().setName("callable 线程 ");
                return Thread.currentThread().getName() + "已经执行...........";

            });

            System.out.println("callableFuture.get() = " + callableFuture.get());

//            executorService.shutdown();  //等待给个线程执行完毕之后才会退出

            executorService.shutdownNow();


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 方法 invokeAny() 接收壹個包含 Callable 对象的集合作为参数。调用该方法不会返回 Future 对象，而是返回集合中某壹個 Callable 对象的结果，
     * <p>
     * 而且无法保证调用之后返回的结果是哪壹個 Callable，只知道它是这些 Callable 中壹個执行结束的 Callable 对象。
     * 如果壹個任务运行完毕或者抛出异常，方法会取消其它的 Callable 的执行。
     */
    public static void testInvokeAny() {

        try {
            //   ExecutorService executorService = Executors.newSingleThreadExecutor();   //单个容量的线程池也可以执行多条线程??


            String result = executorService.invokeAny(callableHashSet);  //调用任意一个线程

            System.out.println("result = " + result);

            executorService.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    private static void testInvokeAll() {


        try {


            Set<Callable<String>> callableHashSet = new HashSet<>();

            callableHashSet.add(() -> "Task c");
            callableHashSet.add(() -> "Task b");
            callableHashSet.add(() -> {
                System.out.println("线程等待 2s.....");
                Thread.sleep(2000);
                return "Task a";
            });

            List<Future<String>> futures = executorService.invokeAll(callableHashSet);

            for (Future<String> future : futures) {
                /*if 你不知道 多久能够返回,  必须设置一个 超时时间,  用来提升系统性能...    */
                System.out.println("future.isCancelled() = " + future.isCancelled());
                System.out.println("future.get() = " + future.get(200, TimeUnit.MILLISECONDS));
                System.out.println("future.isDone() = " + future.isDone());

            }

            System.out.println("executorService.isTerminated() = " + executorService.isTerminated());
            executorService.shutdown();
            /*
            * 当使用awaitTermination时，主线程会处于一种等待的状态，等待线程池中所有的线程都运行完毕后才继续运行。
            * 可以用awaitTermination()方法来判断线程池中是否有继续运行的线程。  注意, 线程池 即使 shutdown  之后 ,
            * 1如果等待的时间超过指定的时间，但是线程池中的线程运行完毕，那么awaitTermination()返回true。执行分线程已结束。
              2如果等待的时间超过指定的时间，但是线程池中的线程未运行完毕，那么awaitTermination()返回false。不执行分线程已结束。
              3如果等待时间没有超过指定时间，等待！
            * */
            executorService.awaitTermination(10, TimeUnit.SECONDS);
            System.out.println("executorService.isTerminated() = " + executorService.isTerminated());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {


        testExecute();
    }


}
